Reject a -H value with no colon - #81
Merged
Merged
Conversation
korya
force-pushed
the
korya-fix-bool-assertion-negation
branch
from
August 8, 2026 13:15
df3d77c to
aacdc72
Compare
korya
force-pushed
the
korya-fix-bare-header
branch
from
August 8, 2026 13:15
f058f11 to
8d2bc4a
Compare
A -H value without a colon was sent as a header with an empty value:
$ http-assert -H 'BareHeader' http://…/echo
{"headers":{"Bareheader":[""], …}}
curl reads the same input as "remove this header". So the two tools take
one input and do opposite things with it, and a user reaching for curl's
idiom got the header they were trying to suppress -- with nothing said
about it. A missing colon is also an ordinary typo, and nothing flagged
that either.
Both forms now exit 71, and the message names the fix, since "no
separator" alone leaves the reader guessing whether an empty value can
be expressed at all:
Invalid value for --header flag: "BareHeader" has no ':' separator;
write "BareHeader:" to send the header with an empty value
A colon with nothing in front of it is refused on the same grounds; it
would have put a nameless header on the wire.
The check lives at the -H call site rather than inside parseHeaderLine,
which is shared with --assert-header, --assert-header-eq and
--assert-header-missing. There a name on its own is meaningful -- it
asserts the header is present -- so the parser is right for one caller
and wrong for the other, and only the caller can tell which.
curl's `-H 'X-Foo;'` spelling for an empty value is not adopted; `X-Foo:`
already expresses it, and the semicolon would need its own parsing rule.
Closes #33
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EMMhgmTkbzAsmeNy97PrP
korya
force-pushed
the
korya-fix-bare-header
branch
from
August 8, 2026 13:20
8d2bc4a to
77c0cc5
Compare
korya
marked this pull request as ready for review
August 8, 2026 13:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
-H 'X-Foo'sent a header with an empty value.curlreads the same input as "remove this header".So one input, two tools, opposite outcomes — and the user reaching for curl's idiom got precisely the header they were trying to suppress, with nothing said about it:
A missing colon is also an everyday typo (
-H 'X-Api-Key abc123'), and nothing flagged that either — the request just went out carrying a header namedX-api-key abc123.Solution
Both forms exit
71, and the message names the fix:"no separator" on its own would leave the reader guessing whether an empty value is expressible at all. It is —
-H 'X-Foo:'— and the error says so rather than making them find out.A colon with nothing in front of it (
-H ': value') is refused on the same grounds: it would have put a nameless header on the wire.The check is at the call site, not in the parser
parseHeaderLineis shared with--assert-header,--assert-header-eqand--assert-header-missing, where a name on its own is not a mistake — it is how you assert the header is present. The parser is therefore right for one caller and wrong for the other, and only the caller knows which. Validating inside it would have broken three working flags to fix one; a test asserts all three still take a bare name.Deliberately not adopted
curl's
-H 'X-Foo;'spelling for "send this empty".X-Foo:already expresses it, and the semicolon would need a parsing rule of its own — today it just becomes part of the header name. Worth doing only alongside curl's removal semantics, which is a larger change than this.Other Changes
TestKnownIssue33BareHeaderSendsEmptyValueis deleted, replaced byTestE2EHeaderRequiresASeparator.One test documents a pflag quirk found while writing it: a solitary
-H ''never reaches this program at all.GetStringArrayreads the value back through pflag's own string form, in which a lone empty entry serialises to[]and parses back as no values. It is harmless — the invocation asks for no header and gets none — but it means-H ''alone cannot be rejected, while-H 'X-Ok: 1' -H ''is. Both are pinned, so the asymmetry is recorded rather than rediscovered.The README gains one sentence in the request options, and the
-Hflag description now states the expected shape.This is a breaking change for anyone using
-H 'X-Foo'to send an empty-valued header. That spelling was ambiguous with curl's opposite meaning, which is the point of the issue;-H 'X-Foo:'is the unambiguous replacement and keeps working.There are no screenshots because there is no rendered UI; this tool's user-visible surface is terminal output, shown inline above.
Closes #33
Related:
🤖 Generated with Claude Code
https://claude.ai/code/session_019EMMhgmTkbzAsmeNy97PrP